package com.redepronik.negosys.invfac.service;

import static com.redepronik.negosys.utils.Utils.compareTo;
import static com.redepronik.negosys.utils.Utils.divide;
import static com.redepronik.negosys.utils.Utils.fechaFormatoString;
import static com.redepronik.negosys.utils.Utils.iva;
import static com.redepronik.negosys.utils.Utils.moraTotal;
import static com.redepronik.negosys.utils.Utils.multiplicar;
import static com.redepronik.negosys.utils.Utils.multiplicarDivide;
import static com.redepronik.negosys.utils.Utils.newBigDecimal;
import static com.redepronik.negosys.utils.Utils.parametro;
import static com.redepronik.negosys.utils.Utils.parse;
import static com.redepronik.negosys.utils.Utils.presentaMensaje;
import static com.redepronik.negosys.utils.Utils.redondear;
import static com.redepronik.negosys.utils.Utils.redondearTotales;
import static com.redepronik.negosys.utils.Utils.timestamp;
import static com.redepronik.negosys.utils.Utils.valorConIva;
import static com.redepronik.negosys.utils.Utils.valorSinIva;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import com.redepronik.negosys.invfac.dao.EgresoDao;
import com.redepronik.negosys.invfac.entity.Bodega;
import com.redepronik.negosys.invfac.entity.Credito;
import com.redepronik.negosys.invfac.entity.Detallecredito;
import com.redepronik.negosys.invfac.entity.Detalleegreso;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Entrada;
import com.redepronik.negosys.invfac.entity.Estadokardex;
import com.redepronik.negosys.invfac.entity.Garante;
import com.redepronik.negosys.invfac.entity.Kardex;
import com.redepronik.negosys.invfac.entity.Local;
import com.redepronik.negosys.invfac.entity.Pagocredito;
import com.redepronik.negosys.invfac.entity.Pagoentrada;
import com.redepronik.negosys.invfac.entity.Producto;
import com.redepronik.negosys.invfac.entityAux.Cantidad;
import com.redepronik.negosys.invfac.entityAux.CantidadFactura;
import com.redepronik.negosys.invfac.entityAux.CantidadesEntradaReporte;
import com.redepronik.negosys.invfac.entityAux.ChequeReporte;
import com.redepronik.negosys.invfac.entityAux.FacturaReporte;
import com.redepronik.negosys.invfac.entityAux.GananciaFacturaReporte;
import com.redepronik.negosys.invfac.entityAux.NumeroCuotasReporte;
import com.redepronik.negosys.invfac.entityAux.VolumenVentaProducto;
import com.redepronik.negosys.rrhh.entity.Ciudad;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.service.ClienteService;
import com.redepronik.negosys.rrhh.service.EmpleadoService;

@Service
public class EgresoServiceImpl implements EgresoService {

	@Autowired
	private EgresoDao egresoDao;

	@Autowired
	private ProductoService productoService;

	@Autowired
	private KardexService kardexService;

	@Autowired
	private ClienteService clienteService;

	@Autowired
	private MoraService moraService;

	@Autowired
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private EmpleadoService empleadoService;

	@Autowired
	private ParametroService parametroService;

	@Autowired
	private LocalService localService;

	public String actualizar(Egreso egreso, Bodega bodega) {
		egresoDao.actualizar(egreso);

		if ((egreso.getTipodocumento().getTipodocumentoid() == 1 || egreso
				.getTipodocumento().getTipodocumentoid() == 8)
				&& bodega != null)
			generarKardexEgreso(egreso.getDetalleegresos(), egreso
					.getTipodocumento().getTipodocumentoid(),
					egreso.getCodigodocumento(), bodega, false);

		return "SAVE";
	}

	public void actualizar(Egreso egreso) {
		egresoDao.actualizar(egreso);
	}

	public FacturaReporte asignar(Detalleegreso detalleEgreso,
			FacturaReporte facturaReporte, int tipoDocumentoId) {
		FacturaReporte reporte = new FacturaReporte();

		Producto producto = productoService.obtenerPorProductoId(detalleEgreso
				.getProducto().getProductoid());

		reporte.setProductoId(producto.getProductoid());
		reporte.setCodigo(producto.getEan());
		reporte.setDescripcion(producto.getNombreimprimir());

		if (tipoDocumentoId == 11)
			reporte.setMotivoBaja(detalleEgreso.getMotivobaja().getNombre());

		if (facturaReporte != null) {
			reporte.setPrecioId(facturaReporte.getPrecioId());
			reporte.setCantidad(facturaReporte.getCantidad());
			reporte.setPrecioUnitVenta(facturaReporte.getPrecioUnitVenta());
			reporte.setDescuentoDolares(facturaReporte.getDescuentoDolares());
			reporte.setDescuentoPorcentaje(facturaReporte
					.getDescuentoPorcentaje());
			reporte.setPromocion(facturaReporte.isPromocion());
			reporte.setEliminar(true);
			if (producto.getIva())
				reporte.setIva("I");
			else
				reporte.setIva("");
		} else {
			reporte.setCantidad(detalleEgreso.getCantidad());
			reporte.setPrecioCosto(detalleEgreso.getPreciocosto());
			reporte.setPrecioUnitVenta(detalleEgreso.getPrecioventa());
			reporte.setDescuentoDolares(detalleEgreso.getDescuento());
			reporte.setDescuentoPorcentaje(multiplicarDivide(
					detalleEgreso.getDescuento(),
					100,
					multiplicar(reporte.getPrecioUnitVenta(),
							reporte.getCantidad())));
			reporte.setPromocion(detalleEgreso.getPromocion());
			reporte.setEliminar(false);
			if (detalleEgreso.getIva())
				reporte.setIva("I");
			else
				reporte.setIva("");

			if (tipoDocumentoId == 8) {
				if (detalleEgreso.getIva() && !detalleEgreso.getPromocion())
					reporte.setPrecioUnitVenta(valorConIva(reporte
							.getPrecioUnitVenta()));
				tipoDocumentoId = 0;
			}
		}

		reporte.setNombreCantidad(productoService.convertirUnidadString(
				reporte.getCantidad(), producto.getProductounidads()));

		if (reporte.isPromocion()) {
			reporte.setDescuentoDolares(multiplicar(
					reporte.getPrecioUnitVenta(), reporte.getCantidad()));
			reporte.setIva("P");
		}

		if (tipoDocumentoId == 2 || tipoDocumentoId == 7
				|| tipoDocumentoId == 0)
			reporte.setEliminar(true);
		else if (tipoDocumentoId == 1 || tipoDocumentoId == 8
				|| tipoDocumentoId == 9)
			reporte.setEliminar(false);

		reporte.setImporte(multiplicar(reporte.getPrecioUnitVenta(),
				reporte.getCantidad()));

		reporte.setPrecioUnitVenta(redondear(reporte.getPrecioUnitVenta()));
		reporte.setDescuentoDolares(redondear(reporte.getDescuentoDolares()));
		reporte.setImporte(redondear(reporte.getImporte()));

		return reporte;
	}

	public CantidadFactura calcularCantidadFactura(
			CantidadFactura cantidadFactura, FacturaReporte facturaReporte,
			String nombreMetodo) {

		try {
			Method metodo = BigDecimal.class.getMethod(nombreMetodo,
					new Class[] { BigDecimal.class });

			BigDecimal total = multiplicar(facturaReporte.getPrecioUnitVenta(),
					facturaReporte.getCantidad());

			if (facturaReporte.getIva().compareToIgnoreCase("I") == 0) {
				cantidadFactura.setSubTotalIva(parse(metodo.invoke(
						cantidadFactura.getSubTotalIva(), total)));
				if (facturaReporte.isPromocion())
					cantidadFactura.setSubTotalIvaPromocion(parse(metodo
							.invoke(cantidadFactura.getSubTotalIvaPromocion(),
									total)));
			} else
				cantidadFactura.setSubTotalNoIva(parse(metodo.invoke(
						cantidadFactura.getSubTotalNoIva(), total)));

			cantidadFactura.setDescuentoProducto(parse(metodo.invoke(
					cantidadFactura.getDescuentoProducto(),
					facturaReporte.getDescuentoDolares())));

			cantidadFactura.setSubTotal(redondear(cantidadFactura
					.getSubTotalIva().add(
							cantidadFactura
									.getSubTotalNoIva()
									.subtract(
											cantidadFactura
													.getDescuentoProducto())
									.subtract(
											cantidadFactura
													.getDescuentoEgreso()))));

			cantidadFactura.setBaseRetencion(redondear(cantidadFactura
					.getSubTotal()));

			cantidadFactura.setIvaPromocion(iva(cantidadFactura
					.getSubTotalIvaPromocion()));

			cantidadFactura.setIva(iva(cantidadFactura.getSubTotalIva()));

			cantidadFactura.setIva(cantidadFactura.getIva().subtract(
					cantidadFactura.getIvaPromocion()));

			cantidadFactura.setTotal(redondear(cantidadFactura.getSubTotal()
					.add(cantidadFactura.getIva())));

		} catch (Exception e) {
			e.printStackTrace();
		}
		return cantidadFactura;
	}

	public CantidadFactura calcularCantidadNotaEntrega(
			CantidadFactura cantidadFactura, FacturaReporte facturaReporte,
			String nombreMetodo) {

		try {
			Method metodo = BigDecimal.class.getMethod(nombreMetodo,
					new Class[] { BigDecimal.class });

			BigDecimal total = multiplicar(facturaReporte.getPrecioUnitVenta(),
					facturaReporte.getCantidad());

			cantidadFactura.setSubTotal(parse(metodo.invoke(
					cantidadFactura.getSubTotal(), total)));

			cantidadFactura.setDescuentoProducto(parse(metodo.invoke(
					cantidadFactura.getDescuentoProducto(),
					facturaReporte.getDescuentoDolares())));

			cantidadFactura.setTotal(redondear(cantidadFactura.getSubTotal()
					.subtract(cantidadFactura.getDescuentoProducto())
					.subtract(cantidadFactura.getDescuentoEgreso())));

		} catch (Exception e) {
			e.printStackTrace();
		}
		return cantidadFactura;
	}

	public void calcularDescuentoDolares(FacturaReporte fr) {
		if (compareTo(fr.getDescuentoDolares(), "0") < 0
				|| compareTo(fr.getDescuentoDolares(), fr.getImporte()) > 0)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"INGRESE UN DESCUENTO VALIDO");
		else {
			fr.setDescuentoPorcentaje(multiplicarDivide(
					fr.getDescuentoDolares(), 100, fr.getImporte()));
			fr.setImporteTotal(redondear(fr.getImporte().subtract(
					fr.getDescuentoDolares())));
			presentaMensaje(FacesMessage.SEVERITY_INFO,
					"SE APLICO EL DESCUENTO CORRECTAMENTE");
		}
	}

	public void calcularDescuentoPorcentaje(FacturaReporte fr) {
		if (compareTo(fr.getDescuentoPorcentaje(), "0") < 0
				|| compareTo(fr.getDescuentoPorcentaje(), "100") > 0)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"INGRESE UN DESCUENTO VALIDO");
		else {
			fr.setDescuentoDolares(multiplicarDivide(fr.getImporte(),
					fr.getDescuentoPorcentaje(), 100));
			fr.setImporteTotal(redondear(fr.getImporte().subtract(
					fr.getDescuentoDolares())));
			presentaMensaje(FacesMessage.SEVERITY_INFO,
					"SE APLICO EL DESCUENTO CORRECTAMENTE");
		}
	}

	public CantidadesEntradaReporte calcularEntrada(Entrada entrada,
			CantidadesEntradaReporte cantidadesEntradaReporte,
			Date fechaEgreso, Date fecha) {
		cantidadesEntradaReporte.setSaldoEntrada(redondearTotales(entrada
				.getSaldo()));
		cantidadesEntradaReporte.setMoraEntrada(newBigDecimal());
		cantidadesEntradaReporte.setTotalEntrada(redondearTotales(entrada
				.getSaldo()));
		if (compareTo(fecha, entrada.getFechamora()) >= 0) {
			BigDecimal mora = moraService.obtenerPorFecha(fechaEgreso)
					.getPorcentaje();
			BigDecimal moraTotal = moraTotal(fecha, entrada.getFechamora(),
					mora);
			cantidadesEntradaReporte.setMoraEntrada(multiplicarDivide(
					moraTotal, entrada.getSaldo()));
			cantidadesEntradaReporte
					.setTotalEntrada(redondearTotales(entrada.getSaldo().add(
							cantidadesEntradaReporte.getMoraEntrada())));
		}
		return cantidadesEntradaReporte;
	}

	public BigDecimal calcularEntradas(Egreso egreso) {
		BigDecimal total = newBigDecimal();
		if (egreso.getEntradas() != null && !egreso.getEntradas().isEmpty())
			for (Entrada entrada : egreso.getEntradas())
				total = total.add(entrada.getCuota());

		return total;
	}

	public NumeroCuotasReporte calcularNumeroCuotasEntradasCreditos(
			Egreso egreso, NumeroCuotasReporte numeroCuotas, Date fecha) {

		if (egreso.getEntradas() != null)
			for (Entrada e : egreso.getEntradas()) {
				if (e.getPagado())
					numeroCuotas.setCuotasPagadasEntrada(numeroCuotas
							.getCuotasPagadasEntrada() + 1);
				else {
					if (compareTo(e.getFechalimite(), fecha) < 0)
						numeroCuotas.setCuotasVencidasEntrada(numeroCuotas
								.getCuotasVencidasEntrada() + 1);
					else
						numeroCuotas.setCuotasNormalesEntrada(numeroCuotas
								.getCuotasNormalesEntrada() + 1);
				}
			}
		numeroCuotas.setCuotasPorPagarEntrada(numeroCuotas
				.getCuotasVencidasEntrada()
				+ numeroCuotas.getCuotasNormalesEntrada());
		numeroCuotas.setCuotasTotalEntrada(numeroCuotas
				.getCuotasPagadasEntrada()
				+ numeroCuotas.getCuotasPorPagarEntrada());

		if (egreso.getCredito() != null
				&& egreso.getCredito().getDetallecreditos() != null)
			for (Detallecredito dc : egreso.getCredito().getDetallecreditos()) {
				if (dc.getPagado())
					numeroCuotas.setCuotasPagadasCredito(numeroCuotas
							.getCuotasPagadasCredito() + 1);
				else {
					if (compareTo(dc.getFechalimite(), fecha) < 0)
						numeroCuotas.setCuotasVencidasCredito(numeroCuotas
								.getCuotasVencidasCredito() + 1);
					else
						numeroCuotas.setCuotasNormalesCredito(numeroCuotas
								.getCuotasNormalesCredito() + 1);
				}
			}
		numeroCuotas.setCuotasPorPagarCredito(numeroCuotas
				.getCuotasVencidasCredito()
				+ numeroCuotas.getCuotasNormalesCredito());
		numeroCuotas.setCuotasTotalCredito(numeroCuotas
				.getCuotasPagadasCredito()
				+ numeroCuotas.getCuotasPorPagarCredito());

		return numeroCuotas;
	}

	public void calcularPrecioCantidad(FacturaReporte fr) {
		if (fr.getPrecioUnitVenta() != null) {
			fr = calcularTotales(fr);
			fr.setPrecioUnitTotal(redondear(fr.getPrecioUnitVenta().add(
					fr.getPrecioUnitIva())));
		}
	}

	public void calcularPrecioPromocion(FacturaReporte fr, boolean iva) {
		fr.setIva(fr.isPromocion() ? "" : iva ? "I" : "");
		if (fr.getCantidad() != null)
			fr = calcularTotales(fr);
		fr.setPrecioUnitIva(iva ? iva(fr.getPrecioUnitVenta())
				: newBigDecimal());
		fr.setPrecioUnitTotal(redondear(fr.getPrecioUnitVenta().add(
				fr.getPrecioUnitIva())));
	}

	public Map<String, Object> calcularPrecioSubTotal(FacturaReporte fr) {
		Map<String, Object> parametro = new HashMap<String, Object>();
		if (fr.getCantidad() == null && fr.getCantidad() <= 0)
			parametro.put("mensaje", new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "MENSAJE DEL SISTEMA",
					"INGRESE UNA CANTIDAD MAYOR QUE CERO"));
		else {
			fr.setPrecioUnitVenta(divide(fr.getSubTotal(), fr.getCantidad()));
			fr = calcularTotales(fr);
			fr.setPrecioUnitTotal(redondear(fr.getPrecioUnitVenta().add(
					fr.getPrecioUnitIva())));
			parametro.put("mensaje", null);
		}
		parametro.put("fr", fr);
		return parametro;
	}

	public void calcularPrecioTotal(FacturaReporte fr) {
		if (fr.getCantidad() != null) {
			if (fr.getIva().compareToIgnoreCase("I") == 0)
				fr.setPrecioUnitVenta(divide(valorSinIva(fr.getImporte()),
						fr.getCantidad()));
			else
				fr.setPrecioUnitVenta(divide(fr.getImporte(), fr.getCantidad()));
			fr = calcularTotales(fr);
			fr.setPrecioUnitTotal(redondear(fr.getPrecioUnitVenta().add(
					fr.getPrecioUnitIva())));
		}
	}

	public void calcularPrecioUnit(FacturaReporte fr) {
		if (fr.getIva().compareToIgnoreCase("I") == 0)
			fr.setPrecioUnitVenta(valorSinIva(fr.getPrecioUnitTotal()));
		else
			fr.setPrecioUnitVenta(fr.getPrecioUnitTotal());

		if (fr.getCantidad() != null)
			fr = calcularTotales(fr);
	}

	public BigDecimal calcularTotal(Egreso egreso) {
		boolean factura = facturaNotaEntrega(egreso.getCodigodocumento());

		int tipoDocumentoId = 0;
		tipoDocumentoId = factura ? 1 : 8;

		CantidadFactura cantidadFactura = new CantidadFactura();
		cantidadFactura.setDescuentoEgreso(egreso.getDescuento());
		for (Detalleegreso detalleEgreso : egreso.getDetalleegresos()) {
			FacturaReporte fr = asignar(detalleEgreso, null, tipoDocumentoId);
			cantidadFactura = factura ? calcularCantidadFactura(
					cantidadFactura, fr, "add") : calcularCantidadNotaEntrega(
					cantidadFactura, fr, "add");
		}
		return redondearTotales(cantidadFactura.getTotal());
	}

	public FacturaReporte calcularTotales(FacturaReporte facturaReporte) {
		if (facturaReporte.getIva().compareToIgnoreCase("I") == 0)
			facturaReporte.setPrecioUnitIva(iva(facturaReporte
					.getPrecioUnitVenta()));
		else
			facturaReporte.setPrecioUnitIva(newBigDecimal());

		facturaReporte.setSubTotal(multiplicar(
				facturaReporte.getPrecioUnitVenta(),
				facturaReporte.getCantidad()));

		if (facturaReporte.getIva().compareToIgnoreCase("I") == 0)
			facturaReporte.setIvaTotal(iva(facturaReporte.getSubTotal()));
		else
			facturaReporte.setIvaTotal(newBigDecimal());

		facturaReporte.setImporte(redondear(facturaReporte.getSubTotal()
				.add(facturaReporte.getIvaTotal())
				.subtract(facturaReporte.getDescuentoDolares())));

		facturaReporte.setImporteTotal(facturaReporte.getImporte());

		return facturaReporte;
	}

	public void cambiarDescuentoFactura(CantidadFactura cfc, CantidadFactura cfp) {
		if (cfp.getDescuentoEgreso().compareTo(cfp.getTotal()) > 0
				|| cfp.getDescuentoEgreso().compareTo(newBigDecimal()) < 0)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"INGRESE UN DESCUENTO VALIDO");
		else {
			cfc.setDescuentoEgreso(cfp.getDescuentoEgreso());
			cfc.setSubTotal(redondear(cfc.getSubTotalIva().add(
					cfc.getSubTotalNoIva().subtract(cfc.getDescuentoEgreso())
							.subtract(cfc.getDescuentoProducto()))));
			cfc.setTotal(redondear(cfc.getSubTotal().add(cfc.getIva())));
			cfc.setBaseRetencion(redondear(cfc.getSubTotal()));
			presentaMensaje(FacesMessage.SEVERITY_INFO,
					"SE APLICO EL DESCUENTO CORRECTAMENTE");
		}
	}

	public void cambiarDescuentoNotaEntrega(CantidadFactura cfc,
			CantidadFactura cfp) {
		if (cfp.getDescuentoEgreso().compareTo(cfp.getTotal()) > 0
				|| cfp.getDescuentoEgreso().compareTo(newBigDecimal()) < 0)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"INGRESE UN DESCUENTO VALIDO");
		else {
			cfc.setDescuentoEgreso(cfp.getDescuentoEgreso());
			cfc.setTotal(redondear(cfc.getSubTotal()
					.subtract(cfc.getDescuentoEgreso())
					.subtract(cfc.getDescuentoProducto())));
			presentaMensaje(FacesMessage.SEVERITY_INFO,
					"SE APLICO EL DESCUENTO CORRECTAMENTE");
		}
	}

	public Long contar() {
		return egresoDao
				.contar("select count(*) from Egreso e where  (e.tipodocumento.tipodocumentoid = 1 or e.tipodocumento.tipodocumentoid = 8) "
						+ "and e.activo=true and e.devolucion=false",
						new Object[] {}).longValue();
	}

	public Long contar(int tipoDocumentoId) {
		return egresoDao
				.contar("select count(*) from Egreso e where e.tipodocumento.tipodocumentoid = ?1",
						new Object[] { tipoDocumentoId }).longValue();
	}

	public Long contar(String cedula) {
		return egresoDao.contar(
				"select count(*) from Egreso e where e.cedularuccliente=?1",
				new Object[] { cedula }).longValue();
	}

	public List<Detalleegreso> detalleEgresoFalse(List<Detalleegreso> list) {
		for (Detalleegreso detalleegreso : list)
			detalleegreso.setEliminar(false);

		return list;
	}

	public void devolucion(Egreso egreso) {
		if (egreso.getTipodocumento().getTipodocumentoid() == 1
				|| egreso.getTipodocumento().getTipodocumentoid() == 4
				|| egreso.getTipodocumento().getTipodocumentoid() == 8
				|| egreso.getTipodocumento().getTipodocumentoid() == 10) {

			List<Detalleegreso> detalleEgresos = duplicarDetalleEgreso(egreso
					.getDetalleegresos());
			for (Detalleegreso detalleegreso : detalleEgresos)
				detalleegreso.setEliminar(true);

			Local local = localService.obtenerPorLocalId(egreso.getLocal()
					.getLocalid());

			generarKardexEgreso(detalleEgresos, egreso.getTipodocumento()
					.getTipodocumentoid(), egreso.getCodigodocumento(), local
					.getBodegalocals().get(0).getBodega(), true);
		}
	}

	public List<Detalleegreso> duplicarDetalleEgreso(
			List<Detalleegreso> detalleEgresos) {
		List<Detalleegreso> list = new ArrayList<Detalleegreso>();
		if (detalleEgresos != null)
			for (Detalleegreso detalleEgreso : detalleEgresos) {
				Detalleegreso dEgreso = new Detalleegreso();
				dEgreso.setOrden(detalleEgreso.getOrden());
				dEgreso.setAutorizacionprecio(detalleEgreso
						.getAutorizacionprecio());
				dEgreso.setCantidad(detalleEgreso.getCantidad());
				dEgreso.setEliminar(detalleEgreso.getEliminar());
				dEgreso.setIva(detalleEgreso.getIva());
				dEgreso.setPreciocosto(detalleEgreso.getPreciocosto());
				dEgreso.setPrecioventa(detalleEgreso.getPrecioventa());
				dEgreso.setDescuento(detalleEgreso.getDescuento());
				dEgreso.setPromocion(detalleEgreso.getPromocion());
				dEgreso.setMotivobaja(detalleEgreso.getMotivobaja());
				dEgreso.setProducto(detalleEgreso.getProducto());
				list.add(dEgreso);
			}

		return list;
	}

	public Egreso duplicarEgreso(Egreso egreso, int tipoDocumentoId) {
		Egreso e = new Egreso();
		e.setActivo(egreso.getActivo());
		e.setAutorizacionanulacion(egreso.getAutorizacionanulacion());
		e.setCajeroid(egreso.getCajeroid());
		e.setClienteFactura(egreso.getCliente());
		e.setCliente(egreso.getCliente());
		e.setCodigodocumento(egreso.getCodigodocumento());
		e.setDescuento(egreso.getDescuento());
		e.setDevolucion(egreso.getDevolucion());
		e.setVendedorid(egreso.getVendedorid());
		e.setFacturainterna(egreso.getFacturainterna());
		e.setFechacierre(egreso.getFechacierre());
		e.setFechainicio(egreso.getFechainicio());
		e.setPadre(egreso.getPadre());
		e.setPagado(egreso.getPagado());

		if (egreso.getCredito() != null) {
			Credito credito = new Credito();
			credito.setInteres(egreso.getCredito().getInteres());
			credito.setMeses(egreso.getCredito().getMeses());
			credito.setMonto(egreso.getCredito().getMonto());
			credito.setPagado(egreso.getCredito().getPagado());

			if (egreso.getCredito().getDetallecreditos() != null) {
				credito.setDetallecreditos(new ArrayList<Detallecredito>());
				for (Detallecredito detalleCredito : egreso.getCredito()
						.getDetallecreditos()) {
					Detallecredito dCredito = new Detallecredito();
					dCredito.setCuota(detalleCredito.getCuota());
					dCredito.setFechalimite(detalleCredito.getFechalimite());
					dCredito.setFechamora(detalleCredito.getFechamora());
					dCredito.setFechapago(detalleCredito.getFechapago());
					dCredito.setMora(detalleCredito.getMora());
					dCredito.setOrden(detalleCredito.getOrden());
					dCredito.setPagado(detalleCredito.getPagado());
					dCredito.setSaldo(detalleCredito.getSaldo());

					if (detalleCredito.getPagocreditos() != null) {
						dCredito.setPagocreditos(new ArrayList<Pagocredito>());
						for (Pagocredito pagoCredito : detalleCredito
								.getPagocreditos()) {
							Pagocredito pCredito = new Pagocredito();
							pCredito.setBanco(pagoCredito.getBanco());
							pCredito.setChequevaucher(pagoCredito
									.getChequevaucher());
							pCredito.setCuentatarjeta(pagoCredito
									.getCuentatarjeta());
							pCredito.setCuota(pagoCredito.getCuota());
							pCredito.setFechacheque(pagoCredito
									.getFechacheque());
							pCredito.setFechapago(pagoCredito.getFechapago());
							pCredito.setPagado(pagoCredito.getPagado());
							pCredito.setFechagiro(pagoCredito.getFechagiro());
							pCredito.setAnulado(pagoCredito.getAnulado());
							pCredito.setDetalle(pagoCredito.getDetalle());
							pCredito.setTipopago(pagoCredito.getTipopago());
							dCredito.addPagocredito(pCredito);
						}
					}
					credito.addDetallecredito(dCredito);
				}
			}

			if (egreso.getCredito().getGarantes() != null) {
				credito.setGarantes(new ArrayList<Garante>());
				List<Persona> listaGarantes = clienteService
						.obtenerGarantesPorCredito(egreso.getCredito()
								.getCreditoid());
				for (Persona p : listaGarantes) {
					Garante g = new Garante();
					g.setCliente(p.getCliente());
					credito.addGarante(g);
				}
			}

			credito.setEgreso(e);
			e.setCredito(credito);
		}

		e.setDetalleegresos(new ArrayList<Detalleegreso>());
		for (Detalleegreso detalleEgreso : duplicarDetalleEgreso(egreso
				.getDetalleegresos()))
			e.addDetalleegreso(detalleEgreso);

		e.setLocal(egreso.getLocal());
		e.setTipodocumento(tipoDocumentoService.obtenerPorId(tipoDocumentoId));

		if (egreso.getEntradas() != null) {
			e.setEntradas(new ArrayList<Entrada>());
			for (Entrada entrada : egreso.getEntradas()) {
				Entrada en = new Entrada();
				en.setCuota(entrada.getCuota());
				en.setFechalimite(entrada.getFechalimite());
				en.setFechamora(entrada.getFechamora());
				en.setFechapago(entrada.getFechapago());
				en.setMora(entrada.getMora());
				en.setPagado(entrada.getPagado());
				en.setSaldo(entrada.getSaldo());
				if (entrada.getPagoentradas() != null) {
					en.setPagoentradas(new ArrayList<Pagoentrada>());
					for (Pagoentrada pagoEntrada : entrada.getPagoentradas()) {
						Pagoentrada pEntrada = new Pagoentrada();
						pEntrada.setBanco(pagoEntrada.getBanco());
						pEntrada.setChequevaucher(pagoEntrada
								.getChequevaucher());
						pEntrada.setCuentatarjeta(pagoEntrada
								.getCuentatarjeta());
						pEntrada.setCuota(pagoEntrada.getCuota());
						pEntrada.setFechacheque(pagoEntrada.getFechacheque());
						pEntrada.setFechapago(pagoEntrada.getFechapago());
						pEntrada.setPagado(pagoEntrada.getPagado());
						pEntrada.setFechagiro(pagoEntrada.getFechagiro());
						pEntrada.setAnulado(pagoEntrada.getAnulado());
						pEntrada.setDetalle(pagoEntrada.getDetalle());
						pEntrada.setTipopago(pagoEntrada.getTipopago());
						en.addPagoentrada(pEntrada);
					}
				}
				e.addEntrada(en);
			}
		}
		// e.setGuiaremision(egreso.getGuiaremision());

		return e;
	}

	public FacesMessage eliminar(Egreso egreso, String login, String pass) {
		Map<String, Object> parametro = empleadoService.autorizacion(login,
				pass);
		FacesMessage fm = (FacesMessage) parametro.get("mensaje");
		Boolean bn = (Boolean) parametro.get("correcto");

		Local local = localService.obtenerPorLocalId(egreso.getLocal()
				.getLocalid());

		Bodega bodega = local.getBodegalocals().get(0).getBodega();

		for (Detalleegreso de : egreso.getDetalleegresos())
			if (kardexService.obtenerSaldoActual(de.getProducto().getEan(),
					bodega.getBodegaid()) == null) {
				bn = false;
				fm = new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"NO HAY COMO ANULAR, EL PRODUCTO NO TIENE KARDEX");
			}

		if (bn)
			if (egreso.getTipodocumento().getTipodocumentoid() == 1
					|| egreso.getTipodocumento().getTipodocumentoid() == 8) {
				egreso.setActivo(false);
				egreso.setAutorizacionanulacion(login);
				egresoDao.actualizar(egreso);

				List<Detalleegreso> detalleEgresos = duplicarDetalleEgreso(egreso
						.getDetalleegresos());
				for (Detalleegreso detalleegreso : detalleEgresos)
					detalleegreso.setEliminar(true);

				generarKardexEgreso(detalleEgresos, egreso.getTipodocumento()
						.getTipodocumentoid(), egreso.getCodigodocumento(),
						bodega, true);

				fm = new FacesMessage(FacesMessage.SEVERITY_INFO,
						"MENSAJE DEL SISTEMA", "ANULO CORRECTAMENTE");
			}

		return fm;
	}

	public FacesMessage eliminarFab(Egreso egreso, String login, String pass) {
		Map<String, Object> parametro = empleadoService.autorizacion(login,
				pass);
		FacesMessage fm = (FacesMessage) parametro.get("mensaje");
		Boolean bn = (Boolean) parametro.get("correcto");

		if (bn)
			if (egreso.getTipodocumento().getTipodocumentoid() == 1
					|| egreso.getTipodocumento().getTipodocumentoid() == 8) {
				egreso.setActivo(false);
				egreso.setAutorizacionanulacion(login);
				egresoDao.actualizar(egreso);

				fm = new FacesMessage(FacesMessage.SEVERITY_INFO,
						"MENSAJE DEL SISTEMA", "ANULO CORRECTAMENTE");
			}

		return fm;
	}

	/* Devuelve: true factura, false nota de entrega */
	public boolean facturaNotaEntrega(String codigoDocumento) {
		String aux = codigoDocumento.substring(0, 3);
		boolean factura = true;
		if (aux.compareToIgnoreCase("FI-") == 0
				&& aux.compareToIgnoreCase(codigoDocumento.substring(3, 6)) == 0)
			factura = false;
		else if (aux.compareToIgnoreCase("NE-") == 0)
			factura = false;

		return factura;
	}

	private void generarKardexEgreso(List<Detalleegreso> detalleEgresos,
			int tipoDocumentoId, String codigoDocumento, Bodega bodega,
			boolean devolucion) {
		List<Detalleegreso> detalleEgresosFinal = sumarCantidades(detalleEgresos);
		int estadoKardexId = 0;

		if (tipoDocumentoId == 11)
			estadoKardexId = 9;
		else if (devolucion)
			estadoKardexId = 3;
		else
			estadoKardexId = 2;

		for (Detalleegreso detalleEgreso : detalleEgresosFinal) {
			Kardex kardex = new Kardex();
			Estadokardex estadoKardex = new Estadokardex();

			estadoKardex.setEstadokardexid(estadoKardexId);

			kardex.setEstadokardex(estadoKardex);
			kardex.setProducto(detalleEgreso.getProducto());
			kardex.setBodega(bodega);
			kardex.setNota(tipoDocumentoService.obtenerPorId(tipoDocumentoId)
					.getNombre() + " - # " + codigoDocumento);
			kardex.setFecha(timestamp());
			kardex.setCantidad(detalleEgreso.getCantidad());
			if (devolucion)
				kardex.setCantidad(kardex.getCantidad() * -1);
			kardex.setPrecio(detalleEgreso.getPreciocosto());
			kardex.setActivo(false);

			kardexService.insertar(kardex);

			Producto producto = productoService
					.obtenerPorProductoId(detalleEgreso.getProducto()
							.getProductoid());
			if (devolucion) {
				Map<String, Object> parametro = kardexService.ponderarPrecio(
						producto, bodega.getBodegaid(), kardex.getPrecio(),
						kardex.getCantidad());
				BigDecimal valorNuevoPrecio = (BigDecimal) parametro
						.get("precio");
				int cantidad = (Integer) parametro.get("cantidad");
				kardexService.insertar(kardexService.generarKardexSaldo(kardex,
						cantidad, valorNuevoPrecio, false));
			} else {
				Kardex kardexSaldo = kardexService.obtenerSaldoActual(
						producto.getEan(), bodega.getBodegaid());
				int cantidad = 0;
				if (kardexSaldo != null) {
					cantidad = kardexSaldo.getCantidad();
					kardexSaldo.setActivo(false);
					kardexService.actualizar(kardexSaldo);
				}
				kardexService.insertar(kardexService.generarKardexSaldo(kardex,
						cantidad, kardex.getPrecio(), false));
			}

		}
	}

	private void inicializar(Egreso egreso) {
		if (egreso.getEntradas() != null)
			for (Entrada entrada : egreso.getEntradas()) {
				entrada.setCuota(redondearTotales(entrada.getCuota()));
				for (Pagoentrada pagosentrada : entrada.getPagoentradas())
					pagosentrada.setCuota(redondearTotales(pagosentrada
							.getCuota()));
			}

		if (egreso.getCredito() != null
				&& egreso.getCredito().getDetallecreditos() != null) {
			while (egreso.getCredito().getDetallecreditos().contains(null))
				egreso.getCredito().getDetallecreditos().remove(null);

			for (Detallecredito detallescredito : egreso.getCredito()
					.getDetallecreditos()) {
				detallescredito.setCuota(redondearTotales(detallescredito
						.getCuota()));
				for (Pagocredito pagoscredito : detallescredito
						.getPagocreditos())
					pagoscredito.setCuota(redondearTotales(pagoscredito
							.getCuota()));
			}
		}
	}

	public String insertar(Egreso egreso, Bodega bodega) {
		egreso.setActivo(true);
		egreso.setDevolucion(false);
		egreso.setFacturainterna(false);
		egreso.setClienteFactura(egreso.getCliente());
		egreso.setTipodocumento(tipoDocumentoService.obtenerPorId(egreso
				.getTipodocumento().getTipodocumentoid()));
		if (egreso.getFechainicio() == null)
			egreso.setFechainicio(timestamp());
		String cedula = SecurityContextHolder.getContext().getAuthentication()
				.getName();
		egreso.setCajeroid(empleadoService
				.obtenerEmpleadoCargoPorCedulaAndCargo(cedula, 4));

		if (egreso.getDescuento() == null)
			egreso.setDescuento(newBigDecimal());

		int secuencia = secuenciaDocuemto(egreso.getTipodocumento()
				.getTipodocumentoid());

		if (egreso.getTipodocumento().getTipodocumentoid() == 1)
			egreso.setCodigodocumento(parametro
					.getCodigoestablecimiento()
					.concat("-")
					.concat(parametro.getCodigoemision().concat("-")
							.concat(String.format("%09d", secuencia))));
		else if (egreso.getTipodocumento().getTipodocumentoid() == 9)
			egreso.setCodigodocumento(egreso.getTipodocumento()
					.getAbreviatura().concat("-")
					.concat(egreso.getCodigodocumento()));
		else
			egreso.setCodigodocumento(egreso.getTipodocumento()
					.getAbreviatura().concat("-")
					.concat(String.format("%010d", secuencia)));

		int c = 1;
		for (Detalleegreso de : egreso.getDetalleegresos()) {
			de.setOrden(c++);
			if (de.getDescuento() == null)
				de.setDescuento(newBigDecimal());
		}

		if (egreso.getTipodocumento().getTipodocumentoid() == 1
				|| egreso.getTipodocumento().getTipodocumentoid() == 8
				|| egreso.getTipodocumento().getTipodocumentoid() == 11) {
			egreso.setDevolucion(false);

			List<Detalleegreso> detalleEgresos = duplicarDetalleEgreso(egreso
					.getDetalleegresos());
			for (Detalleegreso detalleegreso : detalleEgresos)
				detalleegreso.setEliminar(true);

			generarKardexEgreso(detalleEgresos, egreso.getTipodocumento()
					.getTipodocumentoid(), egreso.getCodigodocumento(), bodega,
					false);
		}

		egresoDao.insertar(egreso);

		return "SAVE";
	}

	public void insertar(Egreso egreso) {
		egreso.setActivo(true);
		egreso.setDevolucion(false);
		egreso.setFacturainterna(false);
		egreso.setClienteFactura(egreso.getCliente());
		egreso.setTipodocumento(tipoDocumentoService.obtenerPorId(egreso
				.getTipodocumento().getTipodocumentoid()));
		if (egreso.getFechainicio() == null)
			egreso.setFechainicio(timestamp());
		String cedula = SecurityContextHolder.getContext().getAuthentication()
				.getName();
		egreso.setCajeroid(empleadoService
				.obtenerEmpleadoCargoPorCedulaAndCargo(cedula, 4));

		if (egreso.getDescuento() == null)
			egreso.setDescuento(newBigDecimal());

		int secuencia = secuenciaDocuemto(egreso.getTipodocumento()
				.getTipodocumentoid());

		if (egreso.getTipodocumento().getTipodocumentoid() == 1)
			egreso.setCodigodocumento(parametro
					.getCodigoestablecimiento()
					.concat("-")
					.concat(parametro.getCodigoemision().concat("-")
							.concat(String.format("%09d", secuencia))));
		else if (egreso.getTipodocumento().getTipodocumentoid() == 9)
			egreso.setCodigodocumento(egreso.getTipodocumento()
					.getAbreviatura().concat("-")
					.concat(egreso.getCodigodocumento()));
		else
			egreso.setCodigodocumento(egreso.getTipodocumento()
					.getAbreviatura().concat("-")
					.concat(String.format("%010d", secuencia)));

		int c = 1;
		for (Detalleegreso de : egreso.getDetalleegresos()) {
			de.setOrden(c++);
			if (de.getDescuento() == null)
				de.setDescuento(newBigDecimal());
		}
		egresoDao.insertar(egreso);
	}

	public List<Egreso> obtener(Boolean activo, int tipoDocumentoId) {
		List<Egreso> list = egresoDao
				.obtenerPorHql(
						"select e from Egreso e inner join e.tipodocumento td where td.tipodocumentoid=?1 order by e.fechainicio asc",
						new Object[] { tipoDocumentoId });
		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}

		return list;
	}

	public List<Egreso> obtener(Integer criterioBusquedaEstado,
			String criterioBusquedaCliente, String criterioBusquedaCodigo,
			String criterioBusquedaDetalle, Integer tipoDocumentoId) {

		List<Egreso> list = null;
		if (criterioBusquedaEstado != 0) {
			String consulta = null;
			if (criterioBusquedaEstado == 1)
				consulta = "e.facturainterna=true and e.activo=true";
			else if (criterioBusquedaEstado == 2)
				consulta = "e.facturainterna=false and e.activo=true";
			else if (criterioBusquedaEstado == 3)
				consulta = "e.pagado=true and e.activo=true";
			else if (criterioBusquedaEstado == 4)
				consulta = "e.pagado=false and e.activo=true";
			else if (criterioBusquedaEstado == 5)
				consulta = "e.activo=false";

			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "inner join e.cliente c inner join c.persona p "
					+ "where td.tipodocumentoid=?1 and " + consulta
					+ " order by e.fechainicio asc",
					new Object[] { tipoDocumentoId });
		} else if (criterioBusquedaCliente.compareTo("") != 0
				&& criterioBusquedaCodigo.compareTo("") != 0) {
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos "
									+ "inner join e.cliente c inner join c.persona p "
									+ "where td.tipodocumentoid=?1 "
									+ "and ((p.cedula like ?2 or p.apellido like ?2 or p.nombre like ?2) "
									+ "and e.codigodocumento like ?3) "
									+ "order by e.fechainicio asc",
							new Object[] { tipoDocumentoId,
									"%" + criterioBusquedaCliente + "%",
									"%" + criterioBusquedaCodigo + "%" });
		} else if (criterioBusquedaCliente.compareTo("") != 0) {
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos "
									+ "inner join e.cliente c inner join c.persona p "
									+ "where td.tipodocumentoid=?1 "
									+ "and (p.cedula like ?2 or p.apellido like ?2 or p.nombre like ?2) "
									+ "order by e.fechainicio asc",
							new Object[] { tipoDocumentoId,
									"%" + criterioBusquedaCliente + "%" });
		} else if (criterioBusquedaCodigo.compareTo("") != 0) {
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "where td.tipodocumentoid=?1 "
					+ "and e.codigodocumento like ?2 "
					+ "order by e.fechainicio asc", new Object[] {
					tipoDocumentoId, "%" + criterioBusquedaCodigo + "%" });
		} else if (criterioBusquedaDetalle.compareTo("") != 0) {
			list = new ArrayList<Egreso>();
			List<Egreso> list1 = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos de "
									+ "inner join fetch de.producto p "
									+ "where td.tipodocumentoid=?1 "
									+ "and (p.nombre like ?2 or p.ean like ?2 or p.codigo1 like ?2 or p.codigo2 like ?2) "
									+ "order by e.fechainicio asc",
							new Object[] { tipoDocumentoId,
									"%" + criterioBusquedaDetalle + "%" });
			for (Egreso egreso : list1) {
				egresoDao.evict(egreso);
				list.add(obtenerPorEgresoId(egreso.getEgresoid()));
			}
		}
		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public List<ChequeReporte> obtenerChequesPorCobrarPorFechas(
			Date fechaInicio, Date fechaFin) {
		List<ChequeReporte> list = null;
		List<ChequeReporte> list2 = null;
		if (fechaInicio == null && fechaFin == null) {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||pe.chequevaucher||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro "
									+ "pe.fechacheque as fechaCobro "
									+ "pe.cuota as cuota "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pe.pagado=false and pe.anulado=false "
									+ "order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||pc.chequevaucher||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro "
									+ "pc.fechacheque as fechaCobro "
									+ "pc.cuota as cuota "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pc.pagado=false and pe.anulado=false "
									+ "order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		} else if (fechaInicio == null) {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||pe.chequevaucher||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro "
									+ "pe.fechacheque as fechaCobro "
									+ "pe.cuota as cuota "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pe.pagado=false and pe.anulado=false and pe.fechacheque<='"
									+ fechaFormatoString(fechaFin)
									+ "' order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||pc.chequevaucher||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro "
									+ "pc.fechacheque as fechaCobro "
									+ "pc.cuota as cuota "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pc.pagado=false and and pe.anulado=false pc.fechacheque<='"
									+ fechaFormatoString(fechaFin)
									+ "' order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		} else if (fechaFin == null) {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||pe.chequevaucher||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro "
									+ "pe.fechacheque as fechaCobro "
									+ "pe.cuota as cuota "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pe.pagado=false and pe.anulado=false and pe.fechacheque>='"
									+ fechaFormatoString(fechaInicio)
									+ "' order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||pc.chequevaucher||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro "
									+ "pc.fechacheque as fechaCobro "
									+ "pc.cuota as cuota "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pc.pagado=false and pe.anulado=false and pc.fechacheque>='"
									+ fechaFormatoString(fechaInicio)
									+ "' order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		} else {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||pe.chequevaucher||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro "
									+ "pe.fechacheque as fechaCobro "
									+ "pe.cuota as cuota "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pe.pagado=false and pe.anulado=false and pe.fechacheque >='"
									+ fechaFormatoString(fechaInicio)
									+ "' and pe.fechacheque<='"
									+ fechaFormatoString(fechaFin)
									+ "' order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||pc.chequevaucher||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro "
									+ "pc.fechacheque as fechaCobro "
									+ "pc.cuota as cuota "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pc.pagado=false and pe.anulado=false and pc.fechacheque >='"
									+ fechaFormatoString(fechaInicio)
									+ "' and pc.fechacheque<='"
									+ fechaFormatoString(fechaFin)
									+ "' order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public List<ChequeReporte> obtenerChequesPorFechas(Date fechaInicio,
			Date fechaFin) {
		List<ChequeReporte> list = null;
		List<ChequeReporte> list2 = null;
		if (fechaInicio == null && fechaFin == null) {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select max(pe.pagoentradaid) as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro, "
									+ "pe.fechacheque as fechaCobro, "
									+ "pe.anulado as anulado, "
									+ "pe.detalle as detalle, "
									+ "sum(pe.cuota) as cuota, "
									+ "pe.fechapago as fechaPago, "
									+ "pe.pagado as pagado, "
									+ "'PE' as tabla "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.tipopagoid=3 "
									+ "group by pe.banco, pe.cuentatarjeta, pe.chequevaucher, pe.fechagiro, pe.fechacheque, pe.anulado, pe.detalle, pe.fechapago, pe.pagado "
									+ "order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select max(pc.pagocreditoid) as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro, "
									+ "pc.fechacheque as fechaCobro, "
									+ "pc.anulado as anulado, "
									+ "pc.detalle as detalle, "
									+ "sum(pc.cuota) as cuota, "
									+ "pc.fechapago as fechaPago, "
									+ "pc.pagado as pagado, "
									+ "'PC' as tabla "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.tipopagoid=3 "
									+ "group by pc.banco, pc.cuentatarjeta, pc.chequevaucher, pc.fechagiro, pc.fechacheque, pc.anulado, pc.detalle, pc.fechapago, pc.pagado "
									+ "order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		} else if (fechaInicio == null) {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||'-'||pe.chequevaucher||'-'||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro, "
									+ "pe.fechacheque as fechaCobro, "
									+ "pe.cuota as cuota, "
									+ "pe.anulado as anulado ,"
									+ "pe.pagado as pagado ,"
									+ "'PE' as tabla "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' "
									+ fechaFormatoString(fechaFin)
									+ "' order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||'-'||pc.chequevaucher||'-'||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro, "
									+ "pc.fechacheque as fechaCobro, "
									+ "pc.cuota as cuota, "
									+ "pc.anulado as anulado ,"
									+ "pc.pagado as pagado ,"
									+ "'PC' as tabla "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' "
									+ fechaFormatoString(fechaFin)
									+ "' order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		} else if (fechaFin == null) {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||'-'||pe.chequevaucher||'-'||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro, "
									+ "pe.fechacheque as fechaCobro, "
									+ "pe.cuota as cuota, "
									+ "pe.anulado as anulado ,"
									+ "pe.pagado as pagado ,"
									+ "'PE' as tabla "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pe.fechacheque>='"
									+ fechaFormatoString(fechaInicio)
									+ "' order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||'-'||pc.chequevaucher||'-'||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro, "
									+ "pc.fechacheque as fechaCobro, "
									+ "pc.cuota as cuota, "
									+ "pc.anulado as anulado ,"
									+ "pc.pagado as pagado ,"
									+ "'PC' as tabla "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pc.fechacheque>='"
									+ fechaFormatoString(fechaInicio)
									+ "' order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		} else {
			list = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pe.pagoentradaid||'-'||pe.chequevaucher||'-'||pe.cuentatarjeta as id, "
									+ "pe.banco as banco, "
									+ "pe.cuentatarjeta as numeroCuenta, "
									+ "pe.chequevaucher as numeroCheque, "
									+ "pe.fechagiro as fechaGiro, "
									+ "pe.fechacheque as fechaCobro, "
									+ "pe.cuota as cuota, "
									+ "pe.anulado as anulado ,"
									+ "pe.pagado as pagado ,"
									+ "'PE' as tabla "
									+ "from invfac.pagoentrada pe "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pe.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pe.fechacheque >='"
									+ fechaFormatoString(fechaInicio)
									+ "' and pe.fechacheque<='"
									+ fechaFormatoString(fechaFin)
									+ "' order by pe.fechacheque;",
							ChequeReporte.class);

			list2 = (List<ChequeReporte>) egresoDao
					.obtenerPorSql1(
							"select pc.pagocreditoid||'-'||pc.chequevaucher||'-'||pc.cuentatarjeta as id, "
									+ "pc.banco as banco, "
									+ "pc.cuentatarjeta as numeroCuenta, "
									+ "pc.chequevaucher as numeroCheque, "
									+ "pc.fechagiro as fechaGiro, "
									+ "pc.fechacheque as fechaCobro, "
									+ "pc.cuota as cuota, "
									+ "pc.anulado as anulado ,"
									+ "pc.pagado as pagado ,"
									+ "'PC' as tabla "
									+ "from invfac.pagocredito pc "
									+ "inner join invfac.tipopago tp on (tp.tipopagoid=pc.tipopagoid) "
									+ "where tp.nombre='CHEQUE' and pc.fechacheque >='"
									+ fechaFormatoString(fechaInicio)
									+ "' and pc.fechacheque<='"
									+ fechaFormatoString(fechaFin)
									+ "' order by pc.fechacheque;",
							ChequeReporte.class);
			list.addAll(list2);
		}
		return list;
	}

	public List<Egreso> obtenerEgresosParaCredito(
			String criterioBusquedaCliente, String criterioBusquedaCodigo) {
		List<Egreso> list = null;
		if (criterioBusquedaCliente.compareTo("") != 0
				&& criterioBusquedaCodigo.compareTo("") != 0)
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "left join e.credito cr "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos "
									+ "inner join e.cliente c inner join c.persona p "
									+ "where cr.creditoid is null and td.tipodocumentoid=1 "
									+ "and ((p.cedula like ?1 or p.apellido like ?1 or p.nombre like ?1) "
									+ "and e.codigodocumento like ?2) "
									+ "order by e.fechainicio asc",
							new Object[] { "%" + criterioBusquedaCliente + "%",
									"%" + criterioBusquedaCodigo + "%" });
		else if (criterioBusquedaCliente.compareTo("") != 0)
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "left join e.credito cr "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos "
									+ "inner join e.cliente c inner join c.persona p "
									+ "where cr.creditoid is null and td.tipodocumentoid=1 "
									+ "and (p.cedula like ?1 or p.apellido like ?1 or p.nombre like ?1) "
									+ "order by e.fechainicio asc",
							new Object[] { "%" + criterioBusquedaCliente + "%" });
		else if (criterioBusquedaCodigo.compareTo("") != 0)
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "left join e.credito cr "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "where cr.creditoid is null and td.tipodocumentoid=1 "
					+ "and e.codigodocumento like ?1 "
					+ "order by e.fechainicio asc", new Object[] { "%"
					+ criterioBusquedaCodigo + "%" });

		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	public List<Egreso> obtenerEgresosPorCliente(
			String criterioBusquedaCliente, String criterioBusquedaCodigo,
			Integer tipoDocumentoId) {
		List<Egreso> list = null;
		if (tipoDocumentoId == 0 && criterioBusquedaCodigo.compareTo("") == 0)
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "inner join e.cliente c inner join c.persona p "
					+ "where  p.cedula=?1 and (td.tipodocumentoid=1 "
					+ "or td.tipodocumentoid=2 or td.tipodocumentoid=7 "
					+ "or td.tipodocumentoid=8) order by e.fechainicio asc",
					new Object[] { criterioBusquedaCliente });
		else if (tipoDocumentoId != 0
				&& criterioBusquedaCodigo.compareTo("") != 0)
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "inner join e.cliente c inner join c.persona p "
					+ "where  p.cedula=?1 and td.tipodocumentoid=?2 "
					+ "and e.codigodocumento like ?3 "
					+ "order by e.fechainicio asc", new Object[] {
					criterioBusquedaCliente, tipoDocumentoId,
					"%" + criterioBusquedaCodigo + "%" });
		else if (tipoDocumentoId != 0)
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "inner join e.cliente c inner join c.persona p "
					+ "where  p.cedula=?1 and td.tipodocumentoid=?2 "
					+ "order by e.fechainicio asc", new Object[] {
					criterioBusquedaCliente, tipoDocumentoId });
		else if (criterioBusquedaCodigo.compareTo("") != 0)
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "inner join e.cliente c inner join c.persona p "
					+ "where  p.cedula=?1 and e.codigodocumento like ?2 "
					+ "order by e.fechainicio asc",
					new Object[] { criterioBusquedaCliente,
							"%" + criterioBusquedaCodigo + "%" });

		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	public List<Egreso> obtenerEntregaProducto(Date fechaInicio, Date fechaFin,
			Local local, Ciudad ciudad) {
		return egresoDao.obtenerPorHql("select distinct e from Egreso e "
				+ "inner join fetch e.detalleegresos "
				+ "inner join e.tipodocumento td "
				+ "inner join e.cliente cl inner join cl.persona pe "
				+ "inner join pe.ciudad cd inner join e.local l "
				+ "where (e.activo=true and "
				+ "(td.tipodocumentoid=1 or td.tipodocumentoid=8)) "
				+ "and e.fechainicio >=?1 and e.fechainicio <=?2 "
				+ "and l.localid=?3 and cd.ciudadid=?4 "
				+ "order by e.fechainicio", new Object[] { fechaInicio,
				new Date(fechaFin.getTime() + 86399999), local.getLocalid(),
				ciudad.getCiudadid() });
	}

	public List<Egreso> obtenerFacturasAndNotasEntrega(
			String criterioBusquedaCliente, String criterioBusquedaCodigo,
			String criterioBusquedaDetalle) {
		List<Egreso> list = null;
		if (criterioBusquedaCliente.compareTo("") != 0
				&& criterioBusquedaCodigo.compareTo("") != 0)
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos "
									+ "inner join e.cliente c inner join c.persona p "
									+ "where (td.tipodocumentoid=1 or td.tipodocumentoid=8) "
									+ "and ((p.cedula like ?1 or p.apellido like ?1 or p.nombre like ?1) "
									+ "and e.codigodocumento like ?2) "
									+ "order by e.fechainicio asc",
							new Object[] { "%" + criterioBusquedaCliente + "%",
									"%" + criterioBusquedaCodigo + "%" });
		else if (criterioBusquedaCliente.compareTo("") != 0)
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos "
									+ "inner join e.cliente c inner join c.persona p "
									+ "where (td.tipodocumentoid=1 or td.tipodocumentoid=8) "
									+ "and (p.cedula like ?1 or p.apellido like ?1 or p.nombre like ?1) "
									+ "order by e.fechainicio asc",
							new Object[] { "%" + criterioBusquedaCliente + "%" });
		else if (criterioBusquedaCodigo.compareTo("") != 0)
			list = egresoDao.obtenerPorHql("select distinct e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join fetch e.detalleegresos "
					+ "where (td.tipodocumentoid=1 or td.tipodocumentoid=8) "
					+ "and e.codigodocumento like ?1 "
					+ "order by e.fechainicio asc", new Object[] { "%"
					+ criterioBusquedaCodigo + "%" });
		else if (criterioBusquedaDetalle.compareTo("") != 0) {
			list = new ArrayList<Egreso>();
			List<Egreso> list1 = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join fetch e.detalleegresos de "
									+ "inner join fetch de.producto p "
									+ "where (td.tipodocumentoid=1 or td.tipodocumentoid=8) "
									+ "and (p.nombre like ?1 or p.ean like ?1 or p.codigo1 like ?1 or p.codigo2 like ?1) "
									+ "order by e.fechainicio asc",
							new Object[] { "%" + criterioBusquedaDetalle + "%" });
			for (Egreso egreso : list1) {
				egresoDao.evict(egreso);
				list.add(obtenerPorEgresoId(egreso.getEgresoid()));
			}
		}

		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	public List<Egreso> obtenerFacturasParaGuiaRemision(int localId,
			int ciudadId, String criterioBusquedaCodigo) {
		List<Egreso> list = null;
		if (localId == 0)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"DEBE ESCOJER UN LOCAL");
		else if (ciudadId == 0)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"DEBE ESCOJER UNA CIUDAD");
		else {
			if (criterioBusquedaCodigo.compareTo("") == 0)
				list = egresoDao
						.obtenerPorHql(
								"select distinct e from Egreso e "
										+ "left join e.guiaremision gr "
										+ "inner join e.tipodocumento td "
										+ "inner join e.local l "
										+ "inner join fetch e.detalleegresos "
										+ "inner join e.cliente c inner join c.persona p "
										+ "inner join p.ciudad cd "
										+ "where gr.guiaremisionid is null "
										+ "and td.tipodocumentoid=1 and l.localid=?1 "
										+ "and cd.ciudadid=?2 order by e.fechainicio asc",
								new Object[] { localId, ciudadId });
			else
				list = egresoDao
						.obtenerPorHql(
								"select distinct e from Egreso e "
										+ "left join e.guiaremision gr "
										+ "inner join e.tipodocumento td "
										+ "inner join e.local l "
										+ "inner join fetch e.detalleegresos "
										+ "inner join e.cliente c inner join c.persona p "
										+ "inner join p.ciudad cd "
										+ "where gr.guiaremisionid is null "
										+ "and td.tipodocumentoid=1 and l.localid=?1 "
										+ "and cd.ciudadid=?2 "
										+ "and e.codigodocumento like ?3 order by e.fechainicio asc",
								new Object[] { localId, ciudadId,
										"%" + criterioBusquedaCodigo + "%" });
		}
		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	public GananciaFacturaReporte obtenerGananciaPorFactura(Long egresoId,
			BigDecimal iva) {
		iva = iva.divide(new BigDecimal("100")).add(new BigDecimal("1"));
		return (GananciaFacturaReporte) egresoDao
				.obtenerPorSql1(
						"select e.egresoid as id, e.codigodocumento as codigoDocumento, e.fechainicio as fechaFactura, e.fechacierre as fechaPago, "
								+ "round(sum(case when (de.iva=true) then de.precioventa*"
								+ iva
								+ "*de.cantidad else de.precioventa*de.cantidad end),2) as precioventa, "
								+ "round(sum(case when (de.iva=true) then de.preciocosto*"
								+ iva
								+ "*de.cantidad else de.preciocosto*de.cantidad end),2) as preciocosto, "
								+ "round(sum(de.descuento),2) as descuentoproducto, "
								+ "round(e.descuento,2) as descuentoegreso, "
								+ "0 as ganancia "
								+ "from invfac.egreso e "
								+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
								+ "inner join invfac.tipodocumento td on (e.tipodocumentoid=td.tipodocumentoid) "
								+ "inner join rrhh.cliente cl on (cl.clienteid=e.clienteid)"
								+ "inner join rrhh.persona p on (p.personaid=cl.personaid)"
								+ "where e.pagado=true "
								+ "and e.egresoid="
								+ egresoId
								+ " and de.promocion=false "
								+ "group by e.codigodocumento, e.egresoid "
								+ "order by e.fechainicio asc;",
						GananciaFacturaReporte.class).get(0);
	}

	@SuppressWarnings("unchecked")
	public List<GananciaFacturaReporte> obtenerGananciaPorFechas(
			Date fechaInicio, Date fechaFin, int tipoDocumentoId, BigDecimal iva) {
		List<GananciaFacturaReporte> list = null;
		iva = iva.divide(new BigDecimal("100")).add(new BigDecimal("1"));
		if (fechaInicio == null && fechaFin == null) {
			list = (List<GananciaFacturaReporte>) egresoDao
					.obtenerPorSql1(
							"select e.egresoid as id, e.codigodocumento as codigoDocumento, e.fechainicio as fechaFactura, e.fechacierre as fechaPago, "
									+ "round(sum(case when (de.iva=true) then de.precioventa*"
									+ iva
									+ "*de.cantidad else de.precioventa*de.cantidad end),2) as precioventa, "
									+ "round(sum(case when (de.iva=true) then de.preciocosto*"
									+ iva
									+ "*de.cantidad else de.preciocosto*de.cantidad end),2) as preciocosto, "
									+ "round(sum(de.descuento),2) as descuentoproducto, "
									+ "round(e.descuento,2) as descuentoegreso, "
									+ "0 as ganancia "
									+ "from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.tipodocumento td on (e.tipodocumentoid=td.tipodocumentoid) "
									+ "inner join rrhh.cliente cl on (cl.clienteid=e.clienteid)"
									+ "inner join rrhh.persona p on (p.personaid=cl.personaid)"
									+ "where e.pagado=true "
									+ "and td.tipodocumentoid="
									+ tipoDocumentoId
									+ " and de.promocion=false "
									+ "group by e.codigodocumento, e.egresoid "
									+ "order by e.fechacierre asc;",
							GananciaFacturaReporte.class);
		} else if (fechaInicio == null) {
			list = (List<GananciaFacturaReporte>) egresoDao
					.obtenerPorSql1(
							"select e.egresoid as id, e.codigodocumento as codigoDocumento, e.fechainicio as fechaFactura, e.fechacierre as fechaPago, "
									+ "round(sum(case when (de.iva=true) then de.precioventa*"
									+ iva
									+ "*de.cantidad else de.precioventa*de.cantidad end),2) as precioventa, "
									+ "round(sum(case when (de.iva=true) then de.preciocosto*"
									+ iva
									+ "*de.cantidad else de.preciocosto*de.cantidad end),2) as preciocosto, "
									+ "round(sum(de.descuento),2) as descuentoproducto, "
									+ "round(e.descuento,2) as descuentoegreso, "
									+ "0 as ganancia "
									+ "from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.tipodocumento td on (e.tipodocumentoid=td.tipodocumentoid) "
									+ "inner join rrhh.cliente cl on (cl.clienteid=e.clienteid)"
									+ "inner join rrhh.persona p on (p.personaid=cl.personaid)"
									+ "where e.pagado=true "
									+ "and td.tipodocumentoid="
									+ tipoDocumentoId
									+ " and de.promocion=false "
									+ "and e.fechacierre<='"
									+ fechaFormatoString(fechaFin)
									+ " 23:59:59.999"
									+ "' group by e.codigodocumento, e.egresoid "
									+ "order by e.fechacierre asc;",
							GananciaFacturaReporte.class);
		} else if (fechaFin == null) {
			list = (List<GananciaFacturaReporte>) egresoDao
					.obtenerPorSql1(
							"select e.egresoid as id, e.codigodocumento as codigoDocumento, e.fechainicio as fechaFactura, e.fechacierre as fechaPago, "
									+ "round(sum(case when (de.iva=true) then de.precioventa*"
									+ iva
									+ "*de.cantidad else de.precioventa*de.cantidad end),2) as precioventa, "
									+ "round(sum(case when (de.iva=true) then de.preciocosto*"
									+ iva
									+ "*de.cantidad else de.preciocosto*de.cantidad end),2) as preciocosto, "
									+ "round(sum(de.descuento),2) as descuentoproducto, "
									+ "round(e.descuento,2) as descuentoegreso, "
									+ "0 as ganancia "
									+ "from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.tipodocumento td on (e.tipodocumentoid=td.tipodocumentoid) "
									+ "inner join rrhh.cliente cl on (cl.clienteid=e.clienteid)"
									+ "inner join rrhh.persona p on (p.personaid=cl.personaid)"
									+ "where e.pagado=true "
									+ "and td.tipodocumentoid="
									+ tipoDocumentoId
									+ " and de.promocion=false "
									+ "and e.fechacierre>='"
									+ fechaFormatoString(fechaInicio)
									+ " 00:00:00.000"
									+ "' group by e.codigodocumento, e.egresoid "
									+ "order by e.fechacierre asc;",
							GananciaFacturaReporte.class);
		} else {
			list = (List<GananciaFacturaReporte>) egresoDao
					.obtenerPorSql1(
							"select e.egresoid as id, e.codigodocumento as codigoDocumento, e.fechainicio as fechaFactura, e.fechacierre as fechaPago, "
									+ "round(sum(case when (de.iva=true) then de.precioventa*"
									+ iva
									+ "*de.cantidad else de.precioventa*de.cantidad end),2) as precioventa, "
									+ "round(sum(case when (de.iva=true) then de.preciocosto*"
									+ iva
									+ "*de.cantidad else de.preciocosto*de.cantidad end),2) as preciocosto, "
									+ "round(sum(de.descuento),2) as descuentoproducto, "
									+ "round(e.descuento,2) as descuentoegreso, "
									+ "0 as ganancia "
									+ "from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.tipodocumento td on (e.tipodocumentoid=td.tipodocumentoid) "
									+ "inner join rrhh.cliente cl on (cl.clienteid=e.clienteid)"
									+ "inner join rrhh.persona p on (p.personaid=cl.personaid)"
									+ "where e.pagado=true "
									+ "and td.tipodocumentoid="
									+ tipoDocumentoId
									+ " and de.promocion=false "
									+ "and e.fechacierre >='"
									+ fechaFormatoString(fechaInicio)
									+ " 00:00:00.000"
									+ "' and e.fechacierre <='"
									+ fechaFormatoString(fechaFin)
									+ " 23:59:59.999"
									+ "' group by e.codigodocumento, e.egresoid "
									+ "order by e.fechacierre asc;",
							GananciaFacturaReporte.class);
		}
		return list;
	}

	public List<Egreso> obtenerNoPagadosPorCiudad(int ciudadId) {
		List<Egreso> list = egresoDao.obtenerPorHql(
				"select distinct e from Egreso e "
						+ "inner join fetch e.credito c "
						+ "inner join fetch c.detallecreditos dc "
						+ "left join fetch dc.pagocreditos pc "
						+ "inner join e.cliente cl inner join cl.persona p "
						+ "inner join p.ciudad cd "
						+ "where dc.pagado=false and dc.fechalimite<?1 "
						+ "and cd.ciudadid=?2 order by e.fechainicio",
				new Object[] { new Date(), ciudadId });
		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	public Egreso obtenerPorCodigo(String codigo) {
		Egreso egreso = (Egreso) egresoDao.obtenerPorHql(
				"select e from Egreso e where e.codigodocumento=?1",
				new Object[] { codigo }).get(0);
		inicializar(egreso);
		egreso.setDetalleegresos(detalleEgresoFalse(egreso.getDetalleegresos()));
		actualizar(egreso, null);
		return egreso;
	}

	public List<Egreso> obtenerPorCreditoAlDiaAndFechaLimite(Date fechaLimite) {
		List<Egreso> list = egresoDao
				.obtenerPorHql(
						"select distinct e from Egreso e inner join e.credito c "
								+ "where c.pagado=false and true=all(select dc.pagado from Detallecredito dc "
								+ "where dc.credito.creditoid=c.creditoid and dc.fechalimite<?1) "
								+ "order by e.egresoid",
						new Object[] { fechaLimite });
		if (!list.isEmpty()) {
			for (Egreso egreso : list) {
				inicializar(egreso);
				egreso.setDetalleegresos(detalleEgresoFalse(egreso
						.getDetalleegresos()));
				actualizar(egreso, null);
			}
			return list;
		} else
			return null;
	}

	public List<Egreso> obtenerPorCreditoVencidoAndFechaLimite(Date fechaLimite) {
		List<Egreso> list = egresoDao.obtenerPorHql(
				"select e from Egreso e inner join e.credito c "
						+ "inner join c.detallecreditos dc "
						+ "where dc.pagado=false and dc.fechalimite<?1 "
						+ "group by e.egresoid order by sum(dc.cuota) desc",
				new Object[] { fechaLimite });
		if (!list.isEmpty()) {
			for (Egreso egreso : list) {
				inicializar(egreso);
				egreso.setDetalleegresos(detalleEgresoFalse(egreso
						.getDetalleegresos()));
				actualizar(egreso, null);
			}
			return list;
		} else
			return null;
	}

	public Egreso obtenerPorEgresoId(Long egresoId) {
		Egreso egreso = (Egreso) egresoDao.obtenerPorHql(
				"select distinct e from Egreso e "
						+ "left join fetch e.detalleegresos "
						+ "where e.egresoid=?1", new Object[] { egresoId })
				.get(0);
		inicializar(egreso);
		egreso.setDetalleegresos(detalleEgresoFalse(egreso.getDetalleegresos()));
		actualizar(egreso, null);
		return egreso;
	}

	public List<Egreso> obtenerPorEstado(String cedulaRuc, int tipodocumento,
			String codigoDocumento, Date fechaInicio, Date fechaFin) {
		List<Egreso> list = null;

		if (cedulaRuc != null && cedulaRuc.compareTo("") != 0) {
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join e.cliente c "
									+ "inner join c.persona p "
									+ "where p.cedula=?1 and td.tipodocumentoid=?2 and e.pagado=false "
									+ "order by e.fechainicio asc",
							new Object[] { cedulaRuc, tipodocumento });
		} else if (codigoDocumento != null
				&& codigoDocumento.compareTo("") != 0) {
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join e.cliente c "
									+ "inner join c.persona p "
									+ "where e.codigodocumento like ?1 and td.tipodocumentoid=?2 and e.pagado=false "
									+ "order by e.fechainicio asc",
							new Object[] { "%" + codigoDocumento + "%",
									tipodocumento });
		} else if (fechaInicio != null && fechaFin != null
				&& fechaInicio.before(fechaFin)) {
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join e.cliente c "
									+ "inner join c.persona p "
									+ "where e.fechainicio>=?1 and e.fechainicio<=?2 and td.tipodocumentoid=?3 and e.pagado=false "
									+ "order by e.fechainicio asc",
							new Object[] { fechaInicio,
									new Date(fechaFin.getTime() + 86399999),
									tipodocumento });
		}

		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}
		return list;
	}

	public List<Egreso> obtenerPorCredito(String cedulaRuc) {
		List<Egreso> list = null;
		Persona cliente = null;
		if (!cedulaRuc.equals("") && !cedulaRuc.equals(null))
			cliente = clienteService.obtenerPorCedula(cedulaRuc);
		if (cliente == null) {
			presentaMensaje(FacesMessage.SEVERITY_ERROR, "EL CLIENTE NO EXISTE");
			cliente = new Persona();
		} else {
			list = egresoDao
					.obtenerPorHql(
							"select distinct e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join e.cliente c "
									+ "inner join c.persona p "
									+ "inner join fetch e.credito cr "
									+ "inner join fetch cr.detallecreditos dc "
									+ "where p.cedula=?1 and td.tipodocumentoid=1 and e.pagado=false "
									+ "order by e.fechainicio asc",
							new Object[] { cedulaRuc });
			for (Egreso egreso : list)
				inicializar(egreso);
		}
		return list;
	}

	public List<Egreso> obtenerPorFechasAndTIpoDocumentoAndVendedor(
			Date fechaInicio, Date fechaFin, int tipoDocumentoId, int vendedorId) {
		List<Egreso> list = null;
		if (vendedorId == 0)
			list = egresoDao.obtenerPorHql("select e from Egreso e "
					+ "inner join e.tipodocumento td "
					+ "inner join e.vendedorid v "
					+ "where e.fechainicio >= ?1 and e.fechainicio <= ?2 "
					+ "and td.tipodocumentoid=?3  and e.activo=true "
					+ "order by e.fechainicio asc", new Object[] { fechaInicio,
					new Date(fechaFin.getTime() + 86399999), tipoDocumentoId });
		else
			list = egresoDao
					.obtenerPorHql(
							"select e from Egreso e "
									+ "inner join e.tipodocumento td "
									+ "inner join e.vendedorid v "
									+ "where e.fechainicio >= ?1 and e.fechainicio <= ?2 "
									+ "and td.tipodocumentoid=?3 and v.empleadocargoid=?4 and e.activo=true "
									+ "order by e.fechainicio asc",
							new Object[] { fechaInicio,
									new Date(fechaFin.getTime() + 86399999),
									tipoDocumentoId, vendedorId });
		for (Egreso egreso : list) {
			inicializar(egreso);
			egreso.setDetalleegresos(detalleEgresoFalse(egreso
					.getDetalleegresos()));
			actualizar(egreso, null);
		}

		return list;
	}

	@SuppressWarnings("unchecked")
	public List<VolumenVentaProducto> obtenerVolumenVentaProducto(
			Date fechaInicio, Date fechaFin, int ordenarId) {
		String ordenar = ordenarId == 1 ? "p.nombreimprimir"
				: "sum(de.cantidad) desc";
		return (List<VolumenVentaProducto>) egresoDao
				.obtenerPorSql1(
						"select de.productoid as id, p.ean as ean, p.nombreimprimir as nombre , sum(de.cantidad) as cantidad, p.nombreimprimir as nombreCantidad "
								+ "from invfac.detalleegreso de "
								+ "inner join invfac.egreso e on (de.egresoid=e.egresoid) "
								+ "inner join invfac.producto p on (de.productoid=p.productoid) "
								+ "where e.activo=true "
								+ "and (e.tipodocumentoid= 1 or e.tipodocumentoid= 8) "
								+ "and e.fechainicio >='"
								+ fechaFormatoString(fechaInicio)
								+ " 00:00:00.000"
								+ "' and e.fechainicio <='"
								+ fechaFormatoString(fechaFin)
								+ " 23:59:59.999"
								+ "' group by de.productoid, p.ean, p.nombreimprimir "
								+ "order by " + ordenar + ";",
						VolumenVentaProducto.class);
	}

	public int posicion(FacturaReporte facturaReporte,
			List<Detalleegreso> detalleEgresos, boolean factura) {
		BigDecimal precioVenta = facturaReporte.getPrecioUnitVenta();
		if (!factura && facturaReporte.getIva().compareToIgnoreCase("I") == 0
				&& !facturaReporte.isPromocion())
			precioVenta = valorSinIva(precioVenta);

		for (Detalleegreso detalleEgreso : detalleEgresos)
			if ((facturaReporte.getProductoId().compareTo(detalleEgreso
					.getProducto().getProductoid())) == 0
					&& (facturaReporte.getCantidad().compareTo(detalleEgreso
							.getCantidad())) == 0
					&& (precioVenta.compareTo(redondear(detalleEgreso
							.getPrecioventa())) == 0))
				return detalleEgresos.indexOf(detalleEgreso);

		return -1;
	}

	public void recalcularCantidad(Integer fila, List<FacturaReporte> list,
			List<Detalleegreso> detalleEgresos,
			CantidadFactura cantidadFactura, Integer cantidad, boolean factura) {
		if (fila == null)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"PRESIONE ENTER O TAB PARA CAMBIAR LA CANTIDAD");
		else {
			FacturaReporte f = list.get(fila);

			if (cantidad != f.getCantidad()) {
				cantidadFactura = factura ? calcularCantidadFactura(
						cantidadFactura, f, "subtract")
						: calcularCantidadNotaEntrega(cantidadFactura, f,
								"subtract");

				detalleEgresos.get(fila).setCantidad(cantidad);
				f.setCantidad(cantidad);
				f = asignar(detalleEgresos.get(fila), f, 0);

				cantidadFactura = factura ? calcularCantidadFactura(
						cantidadFactura, f, "add")
						: calcularCantidadNotaEntrega(cantidadFactura, f, "add");

				list.set(fila, f);
			}
		}
	}

	public void recalcularPrecio(Integer fila, int bodegaId,
			List<FacturaReporte> list, List<Detalleegreso> detalleEgresos,
			CantidadFactura cantidadFactura, BigDecimal precio, boolean factura) {
		if (fila == null)
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"PRESIONE ENTER O TAB PARA CAMBIAR EL PRECIO");
		else {
			FacturaReporte f = list.get(fila);

			BigDecimal p = kardexService.obtenerSaldoActual(f.getCodigo(),
					bodegaId).getPrecio();

			if (precio.compareTo(p) < 0)
				presentaMensaje(FacesMessage.SEVERITY_ERROR,
						"EL PRECIO NO DEBE SER MENOR AL PRECIO DE COSTO: " + p);
			else if (precio.compareTo(newBigDecimal()) <= 0)
				presentaMensaje(FacesMessage.SEVERITY_ERROR,
						"EL PRECIO NO DEBE SER MENOR A CERO");
			else if (precio != f.getPrecioUnitVenta()) {
				cantidadFactura = factura ? calcularCantidadFactura(
						cantidadFactura, f, "subtract")
						: calcularCantidadNotaEntrega(cantidadFactura, f,
								"subtract");

				f.setPrecioUnitVenta(precio);
				if (!factura && detalleEgresos.get(fila).getIva()
						&& !f.isPromocion())
					precio = valorSinIva(f.getPrecioUnitVenta());
				detalleEgresos.get(fila).setPrecioventa(precio);

				f = asignar(detalleEgresos.get(fila), f, 0);

				cantidadFactura = factura ? calcularCantidadFactura(
						cantidadFactura, f, "add")
						: calcularCantidadNotaEntrega(cantidadFactura, f, "add");

				list.set(fila, f);
			}
		}
	}

	public CantidadFactura redondearCantidadFactura(
			CantidadFactura cantidadFacturaPresentar,
			CantidadFactura cantidadFacturaCalculos) {
		cantidadFacturaPresentar
				.setSubTotal(redondearTotales(cantidadFacturaCalculos
						.getSubTotal()));
		cantidadFacturaPresentar
				.setDescuentoProducto(redondearTotales(cantidadFacturaCalculos
						.getDescuentoProducto()));
		cantidadFacturaPresentar
				.setDescuentoEgreso(redondearTotales(cantidadFacturaCalculos
						.getDescuentoEgreso()));
		cantidadFacturaPresentar
				.setBaseRetencion(redondearTotales(cantidadFacturaCalculos
						.getBaseRetencion()));
		cantidadFacturaPresentar
				.setSubTotalIva(redondearTotales(cantidadFacturaCalculos
						.getSubTotalIva()));
		cantidadFacturaPresentar
				.setSubTotalIvaPromocion(redondearTotales(cantidadFacturaCalculos
						.getSubTotalIvaPromocion()));
		cantidadFacturaPresentar
				.setIva(redondearTotales(cantidadFacturaCalculos.getIva()));
		cantidadFacturaPresentar
				.setIvaPromocion(redondearTotales(cantidadFacturaCalculos
						.getIvaPromocion()));
		cantidadFacturaPresentar
				.setSubTotalNoIva(redondearTotales(cantidadFacturaCalculos
						.getSubTotalNoIva()));
		cantidadFacturaPresentar
				.setTotal(redondearTotales(cantidadFacturaCalculos.getTotal()));
		return cantidadFacturaPresentar;
	}

	public int secuenciaDocuemto(int tipoDocumentoId) {
		int secuencia = 0;
		if (tipoDocumentoId == 1) {// FACTURA
			secuencia = parametro.getSecuenciafactura() + 1;
			parametro.setSecuenciafactura(secuencia);
			parametroService.actualizar(parametro);
		} else if (tipoDocumentoId == 2) {// COTIZACIÓN
			secuencia = parametro.getSecuenciacotizacion() + 1;
			parametro.setSecuenciacotizacion(secuencia);
			parametroService.actualizar(parametro);
		} else if (tipoDocumentoId == 4) {// DEVOLUCION VENTA
			secuencia = parametro.getSecuenciadevolucion() + 1;
			parametro.setSecuenciadevolucion(secuencia);
			parametroService.actualizar(parametro);
		} else if (tipoDocumentoId == 7) {// PEDIDO
			secuencia = parametro.getSecuenciapedido() + 1;
			parametro.setSecuenciapedido(secuencia);
			parametroService.actualizar(parametro);
		} else if (tipoDocumentoId == 8) {// NOTA ENTREGA
			secuencia = parametro.getSecuenciaentrega() + 1;
			parametro.setSecuenciaentrega(secuencia);
			parametroService.actualizar(parametro);
		} else if (tipoDocumentoId == 10) {// NOTA CREDITO
			secuencia = parametro.getSecuenciacredito() + 1;
			parametro.setSecuenciacredito(secuencia);
			parametroService.actualizar(parametro);
		} else if (tipoDocumentoId == 11) {// BAJA DE INVENTARIO
			secuencia = parametro.getSecuenciabajainventario() + 1;
			parametro.setSecuenciabajainventario(secuencia);
			parametroService.actualizar(parametro);
		}
		return secuencia;
	}

	public List<Detalleegreso> sumarCantidades(
			List<Detalleegreso> detalleEgresos) {
		List<Detalleegreso> detalleEgresosFinal = new ArrayList<Detalleegreso>();

		for (int i = 0; i < detalleEgresos.size(); i++) {
			if (detalleEgresos.get(i).getEliminar()) {
				Detalleegreso detalleEgreso = duplicarDetalleEgreso(
						detalleEgresos.subList(i, i + 1)).get(0);

				for (int j = i + 1; j < detalleEgresos.size(); j++) {
					Detalleegreso dEgreso = detalleEgresos.get(j);
					if (detalleEgreso.getProducto().getProductoid()
							.compareTo(dEgreso.getProducto().getProductoid()) == 0) {
						detalleEgreso.setCantidad(detalleEgreso.getCantidad()
								+ dEgreso.getCantidad());
						detalleEgresos.remove(j);
						j--;
					}
				}
				detalleEgresosFinal.add(detalleEgreso);
			}
		}
		return detalleEgresosFinal;
	}

	@SuppressWarnings("unchecked")
	public Cantidad obtenerCantidadPorProductoOrVendedor(Long producto,
			Date fechaInicio, Date fechaFin, Integer vendedorId) {
		List<Cantidad> list = null;
		if (vendedorId == 0)
			list = (List<Cantidad>) egresoDao
					.obtenerPorSql1(
							"select sum(de.cantidad) as cantidad from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.producto p on (de.productoid=p.productoid) "
									+ "where (e.tipodocumentoid=1 or e.tipodocumentoid=8) "
									+ "and e.activo=true and e.fechainicio>='"
									+ fechaFormatoString(fechaInicio)
									+ " 00:00:00.000' and e.fechainicio<='"
									+ fechaFormatoString(fechaFin)
									+ " 23:59:59.999' and de.productoid="
									+ producto + " group by p.precio;",
							Cantidad.class);
		else
			list = (List<Cantidad>) egresoDao
					.obtenerPorSql1(
							"select sum(de.cantidad) as cantidad from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.producto p on (de.productoid=p.productoid) "
									+ "where (e.tipodocumentoid=1 or e.tipodocumentoid=8) "
									+ "and e.activo=true and e.vendedorid="
									+ vendedorId + " and e.fechainicio>='"
									+ fechaFormatoString(fechaInicio)
									+ " 00:00:00.000' and e.fechainicio<='"
									+ fechaFormatoString(fechaFin)
									+ " 23:59:59.999' and de.productoid="
									+ producto + ";", Cantidad.class);

		Cantidad c = null;
		if (!list.isEmpty())
			if (list.get(0) != null)
				c = list.get(0);
			else
				c = new Cantidad(0);
		else
			c = new Cantidad(0);

		return c;
	}

	@SuppressWarnings("unchecked")
	public Cantidad obtenerCantidadPorProductoPrecioOrVendedor(Long producto,
			Date fechaInicio, Date fechaFin, BigDecimal precio,
			Integer vendedorId) {
		List<Cantidad> list = null;

		if (vendedorId == 0)
			list = (List<Cantidad>) egresoDao
					.obtenerPorSql1(
							"select sum(de.cantidad) as cantidad from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.producto p on (de.productoid=p.productoid) "
									+ "where (e.tipodocumentoid=1 or e.tipodocumentoid=8) "
									+ "and e.activo=true and e.fechainicio>='"
									+ fechaFormatoString(fechaInicio)
									+ " 00:00:00.000' and e.fechainicio<='"
									+ fechaFormatoString(fechaFin)
									+ " 23:59:59.999' and de.productoid="
									+ producto + " and de.preciocosto="
									+ precio + " group by p.precio;",
							Cantidad.class);
		else
			list = (List<Cantidad>) egresoDao
					.obtenerPorSql1(
							"select sum(de.cantidad) as cantidad from invfac.egreso e "
									+ "inner join invfac.detalleegreso de on (e.egresoid=de.egresoid) "
									+ "inner join invfac.producto p on (de.productoid=p.productoid) "
									+ "where (e.tipodocumentoid=1 or e.tipodocumentoid=8) "
									+ "and e.activo=true and e.vendedorid="
									+ vendedorId + " and e.fechainicio>='"
									+ fechaFormatoString(fechaInicio)
									+ " 00:00:00.000' and e.fechainicio<='"
									+ fechaFormatoString(fechaFin)
									+ " 23:59:59.999' and de.productoid="
									+ producto + " and de.preciocosto="
									+ precio + ";", Cantidad.class);
		Cantidad c = null;
		if (!list.isEmpty())
			if (list.get(0) != null)
				c = list.get(0);
			else
				c = new Cantidad(0);
		else
			c = new Cantidad(0);

		return c;
	}
}